//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2006
//
// The class is like std::string but optimized to not occupy additional memory
// if the string is empty.
//

# include "StdAfx.h"
# include "fstring.h"
# include "Globals.h"

void fstring::LoadFromResource (UINT _uiResID) {
	char buf [256];
	const size_t cLen = ::LoadString (g_hResInst, _uiResID, buf, sizeof (buf));
	assert (cLen != 0);

	assign (buf, cLen);
}

void fstring::_assign (const char * _str, size_t _cLen) {
	if (_cLen == 0)
		m_pData = NULL;
	else {
		char * const pData = new char [sizeof (size_t) + _cLen + 1];
		* reinterpret_cast<size_t *> (pData) = _cLen;
		assert (_str);
		::memcpy (pData + sizeof (size_t), _str, _cLen);
		(pData + sizeof (size_t)) [_cLen] = '\0';
		m_pData = pData + sizeof (size_t);
	}
}

void fstring::append (const char * _str, size_t _cLen) {
	if (_cLen == 0)
		return;

	const size_t cSize = size ();

	const size_t cNewSize = cSize + _cLen;
	char * const pNewData = new char [sizeof (size_t) + cNewSize + 1];
	* reinterpret_cast<size_t *> (pNewData) = cNewSize;

	::memcpy (pNewData + sizeof (size_t), m_pData, cSize);
	assert (_str);
	::memcpy (pNewData + sizeof (size_t) + cSize, _str, _cLen);
	(pNewData + sizeof (size_t)) [cNewSize] = '\0';

	if (m_pData)
		delete [] (m_pData - sizeof (size_t));
	m_pData = pNewData + sizeof (size_t);
}

void fstring::append (size_t _cCount, char _ch) {
	if (_cCount == 0)
		return;

	const size_t cSize = size ();

	const size_t cNewSize = cSize + _cCount;
	char * const pNewData = new char [sizeof (size_t) + cNewSize + 1];
	* reinterpret_cast<size_t *> (pNewData) = cNewSize;

	::memcpy (pNewData + sizeof (size_t), m_pData, cSize);
	::memset (pNewData + sizeof (size_t) + cSize, _ch, _cCount);
	(pNewData + sizeof (size_t)) [cNewSize] = '\0';

	if (m_pData)
		delete [] (m_pData - sizeof (size_t));
	m_pData = pNewData + sizeof (size_t);
}

bool fstring::operator == (const fstring & _other) const {
	if (m_pData != NULL && _other.m_pData != NULL) {
		const size_t cSize = * reinterpret_cast<const size_t *> (m_pData - sizeof (size_t));
		if (cSize != * reinterpret_cast<const size_t *> (_other.m_pData - sizeof (size_t)))
			return false;
		return ::memcmp (m_pData, _other.m_pData, cSize) == 0;
	} else if (m_pData == NULL && _other.m_pData == NULL)
		return true;
	else
		return false;
}

bool fstring::operator < (const fstring & _other) const {
	return ::strcmp (c_str (), _other.c_str ()) < 0;
}

void fstring::ToLower () {
	if (m_pData != NULL)
		::CharLowerBuff (m_pData, length ());
}

void fstring::ToUpper () {
	if (m_pData != NULL)
		::CharUpperBuff (m_pData, length ());
}